package com.omuo.utils.collection.facade;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 标准的map转bean，附加转换功能
 *
 * @author omuao
 */
public class StandardMap2BeanWithConvertProcessorImpl extends StandardMap2BeanProcessorImpl implements StandardMap2BeanProcessor {

    /**
     * 转换map
     */
    private Map<String, TypeConverter<? super Object, ?>> converterMap = new HashMap<>(20);

    @Override
    protected void setOutBeanPropertiesData(Field field, Object finalOutBean, Object sourceValue) {
        Class<? extends Object> sourceClass = sourceValue != null ? sourceValue.getClass() : Object.class;

        Class<?> targetClass = field.getType();

        TypeConverter<? super Object, ?> converter = converterMap.get(field.getName());

        if (converter == null) {
            super.setOutBeanPropertiesData(field, finalOutBean, sourceValue);
            return;
        }

        Object resultValue = converter.convert(sourceClass, targetClass, sourceValue);

        super.setOutBeanPropertiesData(field, finalOutBean, resultValue);

    }

    /**
     * 注册转换器
     *
     * @param fieldName 字段名
     * @param converter 类型转换
     */
    public void registerConverter(String fieldName, TypeConverter converter) {
        this.getConverterMap().put(fieldName, converter);
    }

    public Map<String, TypeConverter<? super Object, ?>> getConverterMap() {
        if (converterMap == null) {
            converterMap = new HashMap<>(20);
        }
        return converterMap;
    }

    public void setConverterMap(Map<String, TypeConverter<? super Object, ?>> converterMap) {
        this.converterMap = converterMap;
    }

    /**
     * map 转  bean对象
     *
     * @param data         数据
     * @param mappings     映射
     * @param outBeanClass 输出bean类型
     * @param <R>          返回类型
     * @return 结果bean
     */
    public static <R> R map2Bean(Map<? super Object, ? super Object> data, List<Mapping<Object, String>> mappings, Class<R> outBeanClass, Map<String, TypeConverter<? super Object, ?>> converterMap) {
        StandardMap2BeanWithConvertProcessorImpl standardMap2BeanProcessor = new StandardMap2BeanWithConvertProcessorImpl();
        standardMap2BeanProcessor.setOutBean(null);
        standardMap2BeanProcessor.setMappings(mappings);
        standardMap2BeanProcessor.setOutBeanClass(outBeanClass);
        standardMap2BeanProcessor.setInObjectMap(data);
        standardMap2BeanProcessor.setConverterMap(converterMap);
        standardMap2BeanProcessor.complete();
        return (R) standardMap2BeanProcessor.getOutBean();
    }

    /**
     * list map 转 list bean对象
     *
     * @param data         数据
     * @param mappings     映射
     * @param outBeanClass 输出bean类型
     * @param <R>          返回类型
     * @return 结果bean 列表
     */
    public static <R> List<R> listMap2ListBean(List<Map<? super Object, ? super Object>> data, List<Mapping<Object, String>> mappings, Class<R> outBeanClass, Map<String, TypeConverter<? super Object, ?>> converterMap) {
        StandardMap2BeanWithConvertProcessorImpl standardMap2BeanProcessor = new StandardMap2BeanWithConvertProcessorImpl();
        standardMap2BeanProcessor.setConverterMap(converterMap);
        List<R> result = new ArrayList<>();
        for (Map<? super Object, ? super Object> map : data) {
            standardMap2BeanProcessor.setOutBean(null);
            standardMap2BeanProcessor.setMappings(mappings);
            standardMap2BeanProcessor.setOutBeanClass(outBeanClass);
            standardMap2BeanProcessor.setInObjectMap(map);
            standardMap2BeanProcessor.complete();
            result.add((R) standardMap2BeanProcessor.getOutBean());
        }
        return result;

    }
}
